#include <stdio.h>
#include <string.h>

#include "command.h"
#include "xml.h"
#include "xymodem.h"
#include "message.h"

#define SCRIPT_BUF_SIZE (12*1024)

#define HELP_PAR_ONLY (0x01)
#define HELP_ITEM_ONLY (0x02)
#define HELP_ITEM_ALL (0x04)
#define HELP_ALL (HELP_PAR_ONLY | HELP_ITEM_ALL)
#define HELP_LISTMODULE (0x08)

#define HELP_TREE_LEN (10)

static const char help_usage[] = 
    "-m=[module]"
    "-lm:list module"
    "-p:module usage only"
    "-s:all item only"
    "-a:parent & all item usage"
    "-a=[item]";
    
void list_module(void)
{
    extern u32 _module_base;
    extern u32 _module_end;
    tmodule *cmdtp;
    tmodule *table_start;
    tmodule *table_end;
    int i = 0;
    printf("list_module\n");

    table_start = (tmodule *)&_module_base;
    table_end = (tmodule *)&_module_end;

    for(cmdtp = table_start;cmdtp < table_end;cmdtp++){
        printf("%-8s",cmdtp->name);
        i++;
        if((i%3) == 0){
        printf("\n");
        }
    }

    if((i%3) != 0){
        printf("\n");
    }
}

#define HELP_FILL_STR_1 "+-----------+-"
#define HELP_FILL_STR_2 "            "
#define HELP_FILL_STR_3 "|           +-"

void display_help(char *module_name,char *item_name,int opts)
{
    const titem *item;
    const tmodule *module;
    int i;
    int str_len;
    int argc;
    char *argv[IO_ARGC_MAX + 1];
    char tmp_buf[IO_BUF_SIZE + 4];
    char fill[HELP_TREE_LEN + 1];
    
    printf("displaye_help,module name:%s,item name:%s,ops 0x%x\n"
            ,module_name,item_name,opts);

    if(HELP_LISTMODULE == opts){
        list_module();
        return;
    }

    if(opts & (HELP_ALL | HELP_ITEM_ONLY)){
        if((module = find_module(module_name)) == NULL){
            printf("find module %s failed\n",module_name);
            return;
        }
     }

     if(opts & HELP_PAR_ONLY){
        str_len = strlen(module->name);
        memset(fill,'-',HELP_TREE_LEN - str_len);
        fill[HELP_TREE_LEN - str_len] = '\0';

        printf("%s%s%s",module->name,fill,HELP_FILL_STR_1);
        if(module->usage){
            argc = 0;
            strcpy(tmp_buf,module->usage);
            argc = split_str2argv(tmp_buf,argv,'-');

            for(i=0;i<argc;++i){
                printf("-%-28s",argv[i]);
                if(((i +1) < argc) && (((i + 1) % 2) == 0)){
                    printf("\n%s%s",HELP_FILL_STR_2,HELP_FILL_STR_3);
                }
            }
        }else{
            printf("no usage");
        }
     }

     if(opts & (HELP_ITEM_ALL | HELP_ITEM_ONLY)){
        item = module->item_poi;
        if(NULL == item){
            printf("\n\nno item in module %s\n",module->name);
            return;
        }
        if(opts & HELP_ITEM_ALL){
            for(;item->name != NULL;item++){
                str_len = strlen(item->name);
                memset(fill,'-',HELP_TREE_LEN - str_len);
                fill[HELP_TREE_LEN - str_len - 1] = '+';
                fill[HELP_TREE_LEN - str_len] = '\0';

                printf("\n%s%s%s%s-",HELP_FILL_STR_2,"+-",item->name,fill);

                if(item->usage){
                    argc = 0;
                    strcpy(tmp_buf,item->usage);
                    argc = split_str2argv(tmp_buf,argv,'-');

                    for(i=0;i<argc;++i){
                        printf("-%-28s",argv[i]);
                        if(((i +1) < argc) && (((i + 1) % 2) == 0)){
                            printf("\n%s%s",HELP_FILL_STR_2,HELP_FILL_STR_3);
                        }
                    }                
                }else{
                    printf("no usage");
                }
            }            
        }

        if(opts & HELP_ITEM_ONLY){
            for(;item->name != NULL;item++){
                str_len = strlen(item_name);
                if(strncmp(item->name,item_name,str_len) == 0){
                    if(str_len == strlen(item->name)){
                        break;
                    }
                }
            }
            if(NULL == item){
                printf("\n\nno item in module %s\n",module->name);
                return ;
            }
            str_len = strlen(module->name);
            memset(fill,'-',HELP_TREE_LEN - str_len);
            fill[HELP_TREE_LEN - str_len - 1] = '+';
            fill[HELP_TREE_LEN - str_len] = '\0';

            printf("%s%s%s-","+-",item->name,fill);
            
             if(item->usage){
                argc = 0;
                strcpy(tmp_buf,item->usage);
                argc = split_str2argv(tmp_buf,argv,'-');

                for(i=0;i<argc;++i){
                    printf("-%-28s",argv[i]);
                    if(((i +1) < argc) && (((i + 1) % 2) == 0)){
                        printf("\n%s%s",HELP_FILL_STR_2,HELP_FILL_STR_3);
                    }
                }                
            }else{
                printf("no usage");
            }           
        }
     }
}

cmd_res do_help(int argc,char *argv[])
{
    int opt;
    int help_opts;

    char module[16] = {0};;
    char item[16] = {0};;

    help_opts = HELP_LISTMODULE;
    printf("do_help,argc %d\n",argc);

    reset_argind();
    while((opt = parse_args(argc,argv,"lm:m:p:s:a:i")) != -1){
        printf("opt 0x%x\n",opt);
        switch(opt){
            case 'l'+'m':
            {
                help_opts = HELP_LISTMODULE;
            }
            break;
            case 'm':
            {
                strcpy(module,get_argvalue());
                help_opts = HELP_ALL;
            }
            break;
            case 'p':
            {
                help_opts = HELP_PAR_ONLY;
            }
            break;
            case 's':
            {
                help_opts = HELP_ITEM_ALL;
            }
            break;
            case 'a':
            {
                help_opts = HELP_ALL;
            }
            break;
            case 'i':
            {
                strcpy(item,get_argvalue());
                help_opts = HELP_ITEM_ONLY;
            }
            break;
            default:
            break;
        }
    }

    display_help(module,item,help_opts);
    return OK;
}

ADD_CMD(help,do_help,help_usage);


/**
 * \define struct tcmd
 * \indicate one command.
 */
#define XML_FILE_PATH "/mnt/share/minigui/guiserver/bsp_test.xml"
static char script_buf[SCRIPT_BUF_SIZE];

static cmd_res get_script(void)
{
    char *evn_script;
    int script_len;
    evn_script = script_buf;
    
    printf("get_script\n");
    FILE *fp;
    if((fp = fopen(XML_FILE_PATH,"r")) == NULL){
        printf("Don't open xml file\n");
        return ERR;
    }

    script_len = fread(evn_script,1,SCRIPT_BUF_SIZE,fp);
    if(script_len == 0){
        printf("Don't read xml file\n");
        fclose(fp);
        return ERR;
    }
    evn_script[script_len] = '\0';
    printf("Read num %d,%s\n",script_len,evn_script);
    fclose(fp);
    return OK;
}

static void exec_script(void)
{
    char *name = NULL;
    char *args = args_buf;
    char *cmd = cmd_buf;
    x_node *node = NULL;
    x_node *sub = NULL;
    char sndMsg[64+1] = {0};

    node = xml_parse_read(script_buf,4*1024);
    if(NULL == node){
        printf("script parse error.\n");
        return;
    }
            
    node = xml_get_subnode(node);   
    printf("name=%s\n",node->name.text);
    while(NULL != node){
        name = xml_get_node_name(node);

        if(0 == strncmp(name,"cmd",3)){
                name = xml_get_attribyname(node,"name");
                args = xml_get_attribyname(node,"arg");
                make_cmd(cmd,name,args,FALSE);

                exec_cmdline(cmd);
        }else{        
             if(0 == strncmp(name,"module",5)){
                name = xml_get_attribyname(node,"name");
                args = xml_get_attribyname(node,"arg");
                make_cmd(cmd,name,args,TRUE);
                printf("cmd=%s\n",cmd); 

                if(OK != exec_cmdline(cmd)){
                    memset(sndMsg,0,65);
                    sprintf(sndMsg,"%s init fail\n",name);
                    SendMessage(sndMsg);
                    continue;
                }
                
                memset(sndMsg,0,65);
                sprintf(sndMsg,"%s init success\n",name);
                SendMessage(sndMsg);;
                if(NULL != node->child){/*if has child*/
                    sub = node ->child;
                    while((NULL != sub)&&(0 == strncmp(sub->name.text,"item",4))){
                        name = xml_get_attribyname(sub,"name");
                        args = xml_get_attribyname(sub,"arg");
                        printf("item->name %s\n",name);
                        
                        make_cmd(cmd,name,args,FALSE);
                        
                        if(OK != exec_cmdline(cmd)){
                            memset(sndMsg,0,65);
                            sprintf(sndMsg,"    %s fail\n",name);
                            SendMessage(sndMsg);
                            continue;
                        }else{
                            memset(sndMsg,0,65);
                            sprintf(sndMsg,"    %s success\n",name);
                            SendMessage(sndMsg);
                        }
                        
                        sub = sub->sibling;
                    }
                }
            }
        }
        node = node->sibling;
    }
}

cmd_res do_script(int arg,char *argv[])
{
    if(OK == get_script()){
        exec_script();
        return OK;
    }
    return ERR;    
}

ADD_CMD(script,do_script,NULL);

/**
 * \define struct tcmd
 * \indicate one command.
 */
cmd_res do_auto(int arg,char *argv[])
{
    if(OK == get_script()){
        exec_script();
        return OK;
    }
    return ERR; 
}

ADD_CMD(auto,do_auto,NULL);


/**
 * \define struct tcmd
 * \indicate one command.
 */
cmd_res do_manual(int arg,char *argv[])
{
    if(OK == get_script()){
        char *name = NULL;
        x_node *node = NULL;
        x_node *sub = NULL;
        char sndMsg[64+1] = {0};

        node = xml_parse_read(script_buf,4*1024);
        if(NULL == node){
            printf("script parse error.\n");
            return ERR;
        }
                
        node = xml_get_subnode(node);   
        while(NULL != node){
            name = xml_get_node_name(node);
            if(0 == strncmp(name,"cmd",3)){
                    name = xml_get_attribyname(node,"name");
                    memset(sndMsg,0,65);
                    sprintf(sndMsg,"%s",name);
                    SendMessage(sndMsg);                   
            }else{        
                 if(0 == strncmp(name,"module",5)){
                    name = xml_get_attribyname(node,"name");
                    memset(sndMsg,0,65);
                    sprintf(sndMsg,"%s",name);
                    SendMessage(sndMsg);
                    
                    if(NULL != node->child){/*if has child*/
                        sub = node ->child;
                        while((NULL != sub)&&(0 == strncmp(sub->name.text,"item",4))){
                            name = xml_get_attribyname(sub,"name");
                            memset(sndMsg,0,65);
                            sprintf(sndMsg,"  %s",name);
                            SendMessage(sndMsg);
            
                            sub = sub->sibling;
                        }
                    }
                }
            }
            node = node->sibling;
        }

        return OK;
    }
    
    return ERR; 
}

ADD_CMD(manual,do_manual,NULL);


/**
 * \define struct tcmd
 * \indicate one command.
 */
static const char reg_usage[] = 
    "-b=[register base address]"
    "-s=[word size]"
    "-t=[b|h:w]:byte,halfword,word";
    
cmd_res do_reg(int argc,char *argv[])
{
    printf("do_reg\n");
    return OK;       
}

ADD_CMD(reg,do_reg,reg_usage);